package com.yh.vo;

import cn.hutool.core.bean.OptionalBean;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.yh.entity.Hall;
import com.yh.entity.Movie;
import com.yh.entity.Orderinfo;
import com.yh.utils.Constants;
import lombok.Data;
import org.apache.log4j.Logger;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Data
/**
 * 订单生成记录
 *
 * @author yuhuan
 * @date 2022/01/13
 * */
public class OrderVO implements Serializable {
    /**
     * 日志
     */
    private static final Logger logger = Logger.getLogger(OrderVO.class);

    /**
     * 所属用户编号
     */
    private String userId;
    /**
     * 所属场次编号
     */
    private Integer scheduleId;
    /**
     * 电影票座位信息
     */
    private List<String> orderPosition;
    /**
     * 订单价格
     */
    private Double orderPrice;
    /**
     * 用户权限
     */
    private Integer userRole;
    /**
     * 是否以管理员的身份强制执行
     */
    private Boolean force;

    /**
     * 用户昵称
     */
    private String userName;
    /**
     * 用户账号
     */
    private String userAccount;
    /**
     * 影片名称
     */
    private String movieCnName;
    /**
     * 放映厅名称
     */
    private String hallName;

    /**
     * 订单创建状态 true:创建成功 false:创建失败
     */
    private Boolean createState;
    /**
     * 订单支付页面的跳转路径
     */
    private String payUrl;
    /**
     * 订单剩余的有效时间（单位：秒）
     */
    private Long surplusEffectiveTime;

    /**
     * 放映计划的详细说明 如：今天 11月22日 10:20 放映中
     */
    private String dateTimeDetail;
    /**
     * 放映计划的字符串格式 如：2020-01-01 16:44:06
     */
    private String dateTimeStr;
    /**
     * 影片上映时间的字符串格式详情 如：2020-01-01 16:44:06
     */
    private String movieReleaseDateTimeStr;
    /**
     * 订单创建时间的字符串格式 如：2020-01-01 16:44:06
     */
    private String orderTimeStr;
    /**
     * 订单的状态描述(不再是以符号表示状态 如：待支付)
     */
    private String orderState;
    /**
     * 座位的行索引信息
     */
    private List<String> seatRowIndexs;
    /**
     * 座位的列索引信息
     */
    private List<String> seatColumnIndexs;
    /**
     * 记录位置信息 如：1排12座
     */
    private String seatData;

    /**
     * 订单实体信息
     */
    private Orderinfo orderinfo;
    /**
     * 放映的影片实体信息
     */
    private Movie movie;
    /**
     * 场次详情信息
     */
    private ScheduleVO scheduleVO;

    public OrderVO() {
    }

    public OrderVO(Orderinfo orderinfo) {
        this.orderinfo = orderinfo;
        this.init();
    }

    private void init() {
        seatToSeatDetails();
        initOrderState();
        initOrderTimeStr();
    }

    /**
     * 如果存在座位的定位符号，就将座位的定位符号转换成座位的详细信息分开储存
     * 如：将'1~12'中的1和12分开储存，但索引位置相同；在页面中就可以很方便地将其以'1排12座'的形式展示
     */
    private void seatToSeatDetails() {
        this.seatRowIndexs = new ArrayList<>();
        this.seatColumnIndexs = new ArrayList<>();
        // 开辟缓存区记录位置信息
        StringBuffer buffer = new StringBuffer();
        // 获取到座位的位置信息
        List<String> orderPositions = this.orderinfo.getOrderPosition();
        if (ObjectUtil.isNotEmpty(orderPositions)) {
            // 将定位符转成座位信息
            orderPositions.forEach(orderPosition -> {
                // 截取索引信息
                String rowIndex = orderPosition.split("~")[0];
                this.seatRowIndexs.add(rowIndex);
                String columnIndex = orderPosition.split("~")[1];
                this.seatColumnIndexs.add(columnIndex);
                // 拼接位置信息
                if (buffer.length() != 0) {
                    // 添加逗号分隔
                    buffer.append(",");
                }
                String seatDescribe = rowIndex + "排" + columnIndex + "座";
                buffer.append(seatDescribe);
            });
        }
        this.seatData = buffer.toString();
    }

    /**
     * 如果存在订单的状态符；就将订单状态初始化成可识别的中文格式
     * '0'  ->退票中
     * '-1' ->无法退票
     * '1'  ->待支付
     * '2'  ->已支付
     * '3'  ->退票成功
     */
    private void initOrderState() {
        // 获取订单的状态标识
        Integer orderState = orderinfo.getOrderState();
        if (ObjectUtil.isEmpty(orderState)) {
            return;
        }
        if (orderState == Constants.OrderData.REFUNDING) {
            this.orderState = "退票中";
        }
        if (orderState == Constants.OrderData.UNABLE_REFUN) {
            this.orderState = "无法退票";
        }
        if (orderState == Constants.OrderData.WAIT_PAY) {
            this.orderState = "待支付";
        }
        if (orderState == Constants.OrderData.COMPLETE_PAY) {
            this.orderState = "已支付";
        }
        if (orderState == Constants.OrderData.COMPLETE_REFUN) {
            this.orderState = "退票成功";
        }
    }

    /**
     * 初始化订单的创建时间，将 Date 格式化成 2020-01-01 16:44:06 类型的字符串格式
     */
    private void initOrderTimeStr() {
        Date orderTime = orderinfo.getOrderTime();
        if (ObjectUtil.isEmpty(orderTime)) {
            return;
        }
        this.orderTimeStr = DateUtil.formatDateTime(orderTime);
    }

    /**
     * 初始化订单信息中的放映计划,将日期类型的时间转成中文时间的详情说明 如：今天 11月22日 10:20
     */
    private String initDateTimeExplanation(ScheduleVO scheduleVO) {
        Date scheduleStartTime = scheduleVO.getSchedule().getScheduleStartTime();
        if (ObjectUtil.isEmpty(scheduleStartTime)) {
            logger.debug(">>>>> 计划中缺失重要的播放时间！无法将时间转成中文描述");
            return null;
        }
        // 保存字符串格式的数据
        this.dateTimeStr = DateUtil.formatDateTime(scheduleStartTime);
        // 抽取时间段（如：月-天-时-分）
        int month = DateUtil.month(scheduleStartTime) + 1;
        int day = DateUtil.dayOfMonth(scheduleStartTime);
        int hour = DateUtil.hour(scheduleStartTime, true);
        int minute = DateUtil.minute(scheduleStartTime);
        // 获取前缀和后缀
        String datePrefix = countDatePrefix(scheduleStartTime);
        String dateSuffix = countDateSuffix(scheduleVO);
        // 日期拼接
        String dateTimeDetail = month + "月" + day + "日" + " " + hour + ":" + minute;
        // 如果计算出来的分钟位为0，则补上一个0修正时间；防止'10:00'变成'10:0'
        if (minute == 0) {
            dateTimeDetail = dateTimeDetail + "0";
        }
        if (ObjectUtil.isNotEmpty(datePrefix)) {
            dateTimeDetail = datePrefix + " " + dateTimeDetail;
        }
        if (ObjectUtil.isNotEmpty(dateSuffix)) {
            dateTimeDetail = dateTimeDetail + " " + dateSuffix;
        }
        return dateTimeDetail;
    }

    /**
     * 计算日期的前缀，没有就返回空(如：今天，明天或者后天)
     */
    private String countDatePrefix(Date scheduleStartTime) {
        Date nowTime = new Date();
        // 跳过历史计划
        if (nowTime.before(scheduleStartTime)) {
            // 获取放映日期和今天的天数差异
            long dayDifference = DateUtil.between(scheduleStartTime, nowTime, DateUnit.DAY);
            if (dayDifference == Constants.ScheduleData.FIRST_DAY) {
                return "今天";
            }
            if (dayDifference == Constants.ScheduleData.THE_SECOND_DAY) {
                return "明天";
            }
            if (dayDifference == Constants.ScheduleData.THE_THIRD_DAY) {
                return "后天";
            }
        }
        return null;
    }

    /**
     * 计算日期的后缀，没有就返回空(如：放映中，放映结束)
     */
    private String countDateSuffix(ScheduleVO scheduleVO) {
        if (ObjectUtil.isEmpty(scheduleVO)) {
            return null;
        }
        if (ObjectUtil.isEmpty(scheduleVO.getSchedule())) {
            return countDateSuffix(scheduleVO.getScheduleState());
        }
        return countDateSuffix(scheduleVO.getSchedule().getScheduleStartTime(),
                scheduleVO.getMovieDuration());
    }

    /**
     * 根据影片的开始时间和影片的时长计算日期的后缀，没有就返回空
     */
    private String countDateSuffix(Date scheduleStartTime, int movieDuration) {
        // 计算影片的结束时间
        DateTime showDateTime = DateTime.of(scheduleStartTime);
        DateTime endDateTime = DateUtil.offsetMinute(showDateTime, movieDuration);
        Date nowTime = new Date();
        if (endDateTime.before(nowTime)) {
            return "放映结束";
        }
        if (scheduleStartTime.before(nowTime)) {
            return "放映中";
        }
        return null;
    }

    /**
     * 根据影片的状态计算日期的后缀，没有就返回空
     */
    private String countDateSuffix(String scheduleState) {
        if (scheduleState.equals(Constants.ScheduleData.SHOWING)) {
            return "放映中";
        }
        if (scheduleState.equals(Constants.ScheduleData.END_SHOW)) {
            return "放映结束";
        }
        return null;
    }


    public void setOrderinfo(Orderinfo orderinfo) {
        this.orderinfo = orderinfo;
        this.init();
    }

    public void setMovie(Movie movie) {
        this.movie = movie;
        this.movieCnName = OptionalBean.ofNullable(movie).getBean(Movie::getMovieCnName).get();
        if (ObjectUtil.isNotEmpty(movie)) {
            // 格式化影片的上映时间,将 Date 格式化成 2020-01-01 16:44:06 类型的字符串格式
            this.movieReleaseDateTimeStr = DateUtil.formatDateTime(movie.getMovieReleaseDate());
        }
    }

    public void setScheduleVO(ScheduleVO scheduleVO) {
        this.scheduleVO = scheduleVO;
        if (ObjectUtil.isNotEmpty(scheduleVO)) {
            // 取出影厅的名称
            this.hallName = OptionalBean.ofNullable(scheduleVO.getHall()).getBean(Hall::getHallName).get();
            // 格式化放映日期为中文格式,如果有前缀会添加前缀(如：今天 11月22日 10:20)
            this.dateTimeDetail = initDateTimeExplanation(scheduleVO);
        }
    }
}
